package cn.com.tianpeidong.restaurantadmin.project.admin.role.service.impl;

import cn.com.tianpeidong.restaurantadmin.common.exception.BusinessException;
import cn.com.tianpeidong.restaurantadmin.common.util.msg.MessageUtils;
import cn.com.tianpeidong.restaurantadmin.project.admin.menu.entity.Permission;
import cn.com.tianpeidong.restaurantadmin.project.admin.menu.mapper.PermissionMapper;
import cn.com.tianpeidong.restaurantadmin.project.admin.role.entity.Role;
import cn.com.tianpeidong.restaurantadmin.project.admin.role.entity.RolePermission;
import cn.com.tianpeidong.restaurantadmin.project.admin.role.mapper.RoleMapper;
import cn.com.tianpeidong.restaurantadmin.project.admin.role.service.IRoleService;
import cn.com.tianpeidong.restaurantadmin.project.admin.role.vo.OperateRole;
import cn.com.tianpeidong.restaurantadmin.project.admin.role.vo.RoleVO;
import lombok.NonNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

import static cn.com.tianpeidong.restaurantadmin.common.web.constant.ProjectConstant.*;

/**
 * @author tianpeidong
 * @version 创建时间: 19-4-7 下午6:24
 */
@Service
public class RoleServiceImpl implements IRoleService {

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private PermissionMapper permissionMapper;

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void delete(@NonNull Long roleId) {
        if (roleId.equals(DEFAULT_ADMIN_ROLE_ID)) {
            throw new BusinessException(MessageUtils.message("operate.not.allowed"));
        }
        int count = roleMapper.checkRoleUnderUse(roleId);
        if (count > 0) {
            throw new BusinessException(MessageUtils.message("role.under.use"));
        }
        int res = roleMapper.delete(roleId);
        if (res > 0) {
            roleMapper.deleteRolePermission(roleId);
        }
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Role edit(@NonNull OperateRole operateRole) {
        Long roleId = operateRole.getId();
        if (roleId == null) {
            throw new BusinessException(MessageUtils.message("role.not.exist"));
        }
        if (roleId.equals(DEFAULT_ADMIN_ROLE_ID)) {
            throw new BusinessException(MessageUtils.message("operate.not.allowed"));
        }
        Role roleInDb = roleMapper.getById(operateRole.getId());
        if (roleInDb == null) {
            throw new BusinessException(MessageUtils.message("role.not.exist"));
        }
        int nowVersion = roleInDb.getVersion() + VERSION_STEP;
        String roleName = operateRole.getRoleName();
        Role duplicateRoleName = roleMapper.getByName(roleName);
        if (duplicateRoleName != null && ! duplicateRoleName.getId().equals(roleInDb.getId())) {
            throw new BusinessException(MessageUtils.message("role.name.duplicate"));
        }
        List<RolePermission> list = checkPermissionInfo(operateRole.getPermissionList(), roleInDb.getId(), nowVersion);

        roleInDb.setVersion(nowVersion);
        roleInDb.setRoleName(roleName);

        roleMapper.insertRolePermission(list);

        roleMapper.update(roleInDb);

        return roleInDb;
    }

    private List<RolePermission> checkPermissionInfo(@NonNull List<Long> permissionList, Long roleId, int nowVersion) {

        List<RolePermission> list = new ArrayList<>();

        for (Long permissionId : permissionList) {
            Permission permission = permissionMapper.getById(permissionId);
            if (permission == null) {
                throw new BusinessException(MessageUtils.message("role.permission.not.exist"));
            }
            RolePermission rolePermission = new RolePermission();
            rolePermission.setRoleId(roleId);
            rolePermission.setPermissionId(permissionId);
            rolePermission.setVersion(nowVersion);
            list.add(rolePermission);
        }

        if (list.isEmpty()) {
            throw new BusinessException(MessageUtils.message("role.permission.illegal"));
        }

        return list;
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Role add(OperateRole operateRole) {
        String roleName = operateRole.getRoleName();
        Role duplicateRoleName = roleMapper.getByName(roleName);
        if (duplicateRoleName != null) {
            throw new BusinessException(MessageUtils.message("role.name.duplicate"));
        }
        Role newRole = new Role();
        newRole.setVersion(INIT_VERSION);
        newRole.setRoleName(roleName);
        newRole.setRoleCode("defaultRoleCode");
        newRole.setRemark("defaultRemark");
        roleMapper.insert(newRole);
        List<RolePermission> list = checkPermissionInfo(operateRole.getPermissionList(), newRole.getId(), INIT_VERSION);
        roleMapper.insertRolePermission(list);
        return newRole;
    }

    @Override
    public List<RoleVO> listRole(RoleVO roleVo) {
        return roleMapper.listRole(roleVo);
    }

    @Override
    public Role getRoleById(@NonNull Long id) {
        return roleMapper.getById(id);
    }

}
